package org.dromara.demo.listener;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.excel.context.AnalysisContext;
import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.core.DefaultExcelListener;
import org.dromara.common.excel.core.DropDownOptions;
import org.dromara.demo.domain.vo.ExportDemoVo;

import java.util.List;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：Excel带下拉框的解析处理器
 */
/**
 * 导出演示监听器类，继承自DefaultExcelListener
 * 该类用于处理ExportDemoVo类型数据的Excel导出监听事件
 * 主要实现了对Excel数据写入的监听操作，用于处理数据即将被写入Excel时的逻辑
 */
public class ExportDemoListener extends DefaultExcelListener<ExportDemoVo> {

    /**
     * ExportDemoListener类的构造函数
     * 显式调用父类构造函数以初始化父类属性
     * 避免空指针异常，确保对象初始化正确
     */
    public ExportDemoListener() {
        // 显示使用构造函数，否则将导致空指针
        super(true);
    }

    /**
     * 处理导出数据时的级联下拉字段匹配和数据校验
     * 本方法旨在在数据导出前确保相关联的级联下拉字段（如省、市、县）正确匹配并验证数据的完整性及合法性
     * 首先进行必填字段校验，随后处理级联下拉字段，尝试提取并设置关联的数据ID，最后再次校验确保数据符合规则，最终将数据添加到处理结果中
     *
     * @param data 导出操作所需的具体数据内容
     * @param context 分析操作的上下文环境，可用于传递额外的处理参数或信息
     */
    @Override
    public void invoke(ExportDemoVo data, AnalysisContext context) {
        // 先校验必填
        ValidatorUtils.validate(data, AddGroup.class);

        // 处理级联下拉的部分
        // 获取用户所在的省份信息
        String province = data.getProvince();

        // 获取用户所在的城市信息
        String city = data.getCity();

        // 获取用户所在的地区信息
        String area = data.getArea();
        // 本行用户选择的省
        // 根据提供的省名称，分析并获取对应的选项列表
        List<String> thisRowSelectedProvinceOption = DropDownOptions.analyzeOptionValue(province);
        // 检查选项列表是否包含两个元素，这通常意味着名称和ID都被识别
        if (thisRowSelectedProvinceOption.size() == 2) {
            // 获取省的ID字符串表示
            String provinceIdStr = thisRowSelectedProvinceOption.get(1);
            // 检查获取的ID是否为数字，确保后续可以安全转换为整数
            if (NumberUtil.isNumber(provinceIdStr)) {
                // 严格要求数据的话可以在这里做与数据库相关的判断
                // 例如判断省信息是否在数据库中存在等，建议结合RedisCache做缓存10s，减少数据库调用
                // 将解析得到的省ID设置到数据对象中
                data.setProvinceId(Integer.parseInt(provinceIdStr));
            }
        }

        // 本行用户选择的市
        // 根据给定的城市名，获取与该城市相关的下拉选项列表
        List<String> thisRowSelectedCityOption = DropDownOptions.analyzeOptionValue(city);
        // 如果列表中有两个元素，则尝试处理第二个元素作为城市ID
        if (thisRowSelectedCityOption.size() == 2) {
            String cityIdStr = thisRowSelectedCityOption.get(1);
            // 检查提取出的字符串是否为数字，以确认是否是一个有效的城市ID
            if (NumberUtil.isNumber(cityIdStr)) {
                // 将字符串形式的城市ID转换为整数，并设置到数据对象中
                data.setCityId(Integer.parseInt(cityIdStr));
            }
        }

        // 本行用户选择的县
        // 通过下拉选项分析给定区域的选项，以确定区域配置
        List<String> thisRowSelectedAreaOption = DropDownOptions.analyzeOptionValue(area);
        // 检查分析出的选项是否包含确切的两个元素，这通常包含区域的相关信息
        if (thisRowSelectedAreaOption.size() == 2) {
            // 获取可能包含区域ID的字符串
            String areaIdStr = thisRowSelectedAreaOption.get(1);
            // 验证获取的字符串是否为数字，以确保它可能是区域ID
            if (NumberUtil.isNumber(areaIdStr)) {
                // 将验证过的区域ID字符串转换为整数，并设置到数据对象中
                data.setAreaId(Integer.parseInt(areaIdStr));
            }
        }

        // 处理完毕以后判断是否符合规则
        ValidatorUtils.validate(data, EditGroup.class);

        // 添加到处理结果中
        getExcelResult().getList().add(data);
    }
}
